import { Comment } from '@babel/types';
import { isNotEmptyObject } from '../utils';

import {
    marks,
    parseCommentForEventMark,
    parseCommentForPublicMark,
    parseCommentForOptionMark,
    parseCommentForParamMark,
    parseCommentForReturnsMark,
    parseCommentForArgMark,
    isEventMark,
    isPureContent,
    isCommentBlock
} from './mark';

import { IFunction, IParam, IOption } from '../types/normal';

export * from './mark';
export * from './splic';

/**
 * 解析块注释，不包括函数注释的解析
 */
export function parseCommentBlock(comment: Comment) {
    if (isCommentBlock(comment)) {
        const info: {
            desp?: string;
            options?: Array<IOption>;
            events?: ReturnType<typeof parseCommentForEventMark>;
            public?: ReturnType<typeof parseCommentForPublicMark>;
        } = {};

        const eventMarkInfo = parseCommentForEventMark(comment);
        if (eventMarkInfo.length) info.events = eventMarkInfo;

        const publicMarkInfo = parseCommentForPublicMark(comment);
        if (publicMarkInfo) info.public = publicMarkInfo;

        const comments = splitCommentBlock(comment.value);
        comments.forEach((str, idx) => {
            if (str.startsWith(marks.option)) {
                const option = parseCommentForOptionMark(str);
                if (option) info.options = (info.options || []).concat([option]);
                // ...
            } else if (!info.desp) {
                if (isPureContent(str)) {
                    info.desp = str;
                } else if (str.startsWith(marks.description) && isPureContent(comments[idx - 1])) {
                    const desp = str.split(/\s+/)[1] || '';
                    if (desp) info.desp = desp;
                }
            }
        });

        return isNotEmptyObject(info) ? info : undefined;
    }
}

/**
 * 解析函数注释
 *
 * 解析单个块注释或行注释的信息
 */
export function parseCommentForFunction(comment: Comment) {
    const info: IFunction = {};
    if (isCommentBlock(comment)) {
        for (let str of splitCommentBlock(comment.value)) {
            if (str.startsWith(marks.description)) {
                const desp = str.split(/\s+/)[1];
                if (desp) info.desp = desp;
                // ...
            } else if (str.startsWith(marks.param)) {
                const param = parseCommentForParamMark(str);
                if (param) info.params = (info.params || []).concat([param]);
                // ...
            } else if (str.startsWith(marks.return) || str.startsWith(marks.returns)) {
                const ret = parseCommentForReturnsMark(str);
                if (ret) info.returns = ret;
                // ...
            } else if (!info.desp) {
                info.desp = str;
            }
        }
    } else {
        const desp = comment.value.trim();
        if (desp) info.desp = desp;
    }
    return info;
}

/**
 * 解析 vue event 注解
 *
 * 支持多个块注释和多个行注释的写法
 */
export function parseCommentForVueEvent(comment: Comment | readonly Comment[]) {
    let info: {
        name?: string;
        desp?: string;
        params?: Array<IParam>;
    } = {};

    const parser = (commentStr: string) => {
        for (let str of splitCommentBlock(commentStr)) {
            if (str.startsWith(marks.description)) {
                const desp = str.split(/\s+/)[1] || '';
                if (desp) info.desp = desp;
                // ...
            } else if (str.startsWith(marks.param)) {
                const param = parseCommentForParamMark(str);
                if (param) info.params = (info.params || []).concat([param]);
                // ...
            } else if (str.startsWith(marks.arg)) {
                const param = parseCommentForArgMark(str);
                if (param) info.params = (info.params || []).concat([param]);
                // ...
            } else if (!info.desp) {
                info.desp = str;
            }
        }
    };

    if (comment instanceof Array) {
        let commentStr = '';
        comment.forEach(t => {
            commentStr += t.value.trim() + '\n';
        });
        parser(commentStr);
    } else {
        if (isCommentBlock(comment)) {
            if (isEventMark(comment)) {
                const infos = parseCommentForEventMark(comment);
                if (infos.length) info = infos[0];
            } else {
                parser(comment.value);
            }
        } else {
            const desp = comment.value.trim();
            if (desp) info.desp = desp;
        }
    }

    return isNotEmptyObject(info) ? info : undefined;
}

/**
 * 拆分块注释
 */
export function splitCommentBlock(commentBlock: string) {
    return commentBlock.split('\n').map(str => {
        return str
            .trim()
            .replace(/^\**\s*/, '')
            .replace(/\\r$/, '');
    });
}
